#pragma execution_character_set("utf-8")

/*
 * host_loader.cpp
 *
 *  Created on: 2023年9月14日
 *      Author: Dylan.Gao
 */

#include <dm/export.hpp>

#define DM_API_OS_SYS DM_API_EXPORT

#include <dm/os/sys/host_loader.hpp>
#include <dm/env/cfg.hpp>
#include <dm/string/stringlist.hpp>
#include <dm/os/log/logger.hpp>

namespace dm{
namespace os{
namespace sys{

static const char* logModule = "CHostLoader.sys.os.dm";

CHostLoader::CHostLoader():m_db(),m_resultSet(){
	log().debug(THISMODULE "创建对象");
}

CHostLoader::~CHostLoader(){
	m_resultSet = NULL;
	m_db = NULL;
	log().debug(THISMODULE "销毁对象");
}

bool CHostLoader::createTable(){
	if( !m_db ){
		dm::env::CCfg& cfg = dm::env::CCfg::ins();
		m_db = dm::os::createDb(cfg.sys_dbName().c_str(),cfg.sys_dbHost().c_str(), cfg.sys_dbEngine().c_str(), cfg.sys_dbPort());
		if( !m_db->connect(cfg.sys_dbUsr().c_str(), cfg.sys_dbPwd().c_str()) )
			return false;
	}

	switch( m_db->dbType() ){
	case dm::os::CDb::DtSqlite:
		return m_db->exec("CREATE TABLE t_host (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name varchar(64) NOT NULL UNIQUE, descr varchar(255) NOT NULL, sound varchar(255), group_id integer(10), net_a integer(10), net_b integer(10), com_a integer(10), com_b integer(10), com_c integer(10))");
	case dm::os::CDb::DtPg:
		return m_db->exec("CREATE TABLE t_host (id SERIAL NOT NULL, name varchar(64) NOT NULL UNIQUE, descr varchar(255) NOT NULL, sound varchar(255), group_id int4, net_a int4, net_b int4, com_a int4, com_b int4, com_c int4, PRIMARY KEY (id))");
	case dm::os::CDb::DtMysql:
		return m_db->exec("CREATE TABLE t_host (id int(10) NOT NULL AUTO_INCREMENT, name varchar(64) NOT NULL UNIQUE, descr varchar(255) NOT NULL, sound varchar(255), group_id int(10), net_a int(10), net_b int(10), com_a int(10), com_b int(10), com_c int(10), PRIMARY KEY (id))");
	default:
		return false;
	}
}

bool CHostLoader::addHost( id_t& id,const char* name,const char* descr){
	if( !m_db ){
		dm::env::CCfg& cfg = dm::env::CCfg::ins();
		m_db = dm::os::createDb(cfg.sys_dbName().c_str(),cfg.sys_dbHost().c_str(), cfg.sys_dbEngine().c_str(), cfg.sys_dbPort());
		if( !m_db->connect(cfg.sys_dbUsr().c_str(), cfg.sys_dbPwd().c_str()) )
			return false;
	}

	char sql[512];
	std::sprintf(sql,"INSERT INTO t_host(name,descr) values ('%s','%s')",name,descr);
	id = m_db->execWithLastId(sql);

	return id>=0;
}

bool CHostLoader::delHost( const id_t& id ){
	if( !m_db ){
		dm::env::CCfg& cfg = dm::env::CCfg::ins();
		m_db = dm::os::createDb(cfg.sys_dbName().c_str(),cfg.sys_dbHost().c_str(), cfg.sys_dbEngine().c_str(), cfg.sys_dbPort());
		if( !m_db->connect(cfg.sys_dbUsr().c_str(), cfg.sys_dbPwd().c_str()) )
			return false;
	}

	char sql[512];
	std::sprintf(sql,"DELETE FROM t_host WHERE id=%d",id);
	return m_db->exec(sql);
}

bool CHostLoader::delHost( const char* name ){
	if( !m_db ){
		dm::env::CCfg& cfg = dm::env::CCfg::ins();
		m_db = dm::os::createDb(cfg.sys_dbName().c_str(),cfg.sys_dbHost().c_str(), cfg.sys_dbEngine().c_str(), cfg.sys_dbPort());
		if( !m_db->connect(cfg.sys_dbUsr().c_str(), cfg.sys_dbPwd().c_str()) )
			return false;
	}

	char sql[512];
	std::sprintf(sql,"DELETE FROM t_host WHERE name='%s'",name);
	return m_db->exec(sql);
}

bool CHostLoader::addALoaded( store_record_t& r ){
	id_t id;
    store_record_t::CIdReader idReader;
	if( !r.get(&id, idReader) ){
		log().warnning(THISMODULE "读取ID失败");
		return false;
	}

	m_loadedRecordsId.push_back(id);

	return true;
}

bool CHostLoader::filterLoaded(){
	if( !m_db ){
		dm::env::CCfg& cfg = dm::env::CCfg::ins();
		m_db = dm::os::createDb(cfg.sys_dbName().c_str(),cfg.sys_dbHost().c_str(), cfg.sys_dbEngine().c_str(), cfg.sys_dbPort());
		if( !m_db->connect(cfg.sys_dbUsr().c_str(), cfg.sys_dbPwd().c_str()) ){
			log().warnning(THISMODULE "连接数据库失败");
			return false;
		}
	}

	if( m_loadedRecordsId.size()==0 ){
		m_resultSet = m_db->query("select id,name,descr,net_a,net_b from t_host order by id");
		if( !m_resultSet ){
			log().warnning(THISMODULE "查询记录失败");
			return false;
		}

		return true;
	}

	dm::string::CStringList sql;
	char ids[64];
	sql.append("SELECT id,name,descr,net_a,net_b from t_host where id not in (");
	for( int i=0;i<m_loadedRecordsId.size();++i ){
		if( i==0 )
			std::sprintf(ids,"%ld",m_loadedRecordsId[i]);
		else
			std::sprintf(ids,",%ld",m_loadedRecordsId[i]);

		sql.append(ids);
	}
	sql.append(") order by id");

	m_resultSet = m_db->query(sql.toString().c_str());
	if( !m_resultSet ){
		log().warnning(THISMODULE "查询结果失败");
		return false;
	}

	return true;
}

/**
 * 移动记录
 * @return
 */
bool CHostLoader::next(){
	if( m_resultSet )
		return m_resultSet->next();

	log().debug(THISMODULE "记录未初始化");
	return false;
}

/**
 * 记录加载器
 */
class CHostRecordLoader:public CHostLoader::store_record_t::CLoader{
	dm::os::CResultSet* m_rs;
public:
	CHostRecordLoader( dm::os::CResultSet* rs ):m_rs(rs){}

	bool loadRecord( SHostInfo& i,SHostState& v,CTimeStamp& ts,CRunTimeStamp& rts,const CTimeStamp& tsNow,const CRunTimeStamp& rtsNow ){
		if( !m_rs )
			return false;

		i.id = m_rs->asInt64(0);
		i.name = m_rs->asString(1).c_str();
		i.desc = m_rs->asString(2).c_str();
		i.net1_ip.set(m_rs->asString(3).c_str());
		i.net2_ip.set(m_rs->asString(4).c_str());

		v.state = v.SUnknow;
		v.net1State = v.NsUnknow;
		v.net2State = v.NsUnknow;

		ts = tsNow;
		rts = rtsNow;

		return true;
	}
};

/**
 * 加载记录
 * @param record
 * @return
 */
bool CHostLoader::loadRecord( store_record_t& record ){
	if( !m_resultSet ){
		log().info(THISMODULE "结果集不存在");
		return false;
	}

	SHostInfo hostInfo;
	hostInfo.id = m_resultSet->asInt64(0);
	hostInfo.name = m_resultSet->asString(1);
	hostInfo.desc = m_resultSet->asString(2,"");
	hostInfo.net1_ip.set(m_resultSet->asString(3,"").c_str());
	hostInfo.net2_ip.set(m_resultSet->asString(4,"").c_str());

	SHostState hostState;
	hostState.init();

    store_record_t::CNormalLoader loader(&hostInfo,&hostState);

	return record.reload(loader, m_tsNow, m_rtsNow);
}

bool CHostLoader::reloadRecord( store_record_t& record ){
	if( !m_db ){
		dm::env::CCfg& cfg = dm::env::CCfg::ins();
		m_db = dm::os::createDb(cfg.sys_dbName().c_str(),cfg.sys_dbHost().c_str(), cfg.sys_dbEngine().c_str(), cfg.sys_dbPort());
		if( !m_db->connect(cfg.sys_dbUsr().c_str(), cfg.sys_dbPwd().c_str()) ){
			log().warnning(THISMODULE "连接数据库失败");
			return false;
		}
	}

	char sql[128];
	std::sprintf(sql,"SELECT id,name,descr,net_a,net_b from t_host where id=%d",record.info.id);

	m_resultSet = m_db->query(sql);
	if( !m_resultSet || !m_resultSet->next() ){
		log().warnning(THISMODULE "查询记录(id:%d)失败",record.info.id);
		return false;
	}

	return loadRecord(record);
}

}
}
}
